package com.sspro.simplertmp.core.encode;

import android.content.Context;
import android.media.AudioRecord;
import android.media.MediaRecorder;
import android.os.AsyncTask;
import android.util.Log;

import com.sspro.simplertmp.core.AudioProfile;
import com.sspro.simplertmp.core.BasicProfile;
import com.sspro.simplertmp.core.utils.Constant;
import com.sspro.simplertmp.core.utils.KitUtil;
import com.wbapp.common.jni.JniProxy;

import java.util.Arrays;

public class AudioEncodeFun {

    private byte[] mBuffer;
    private byte[] mCacheData;
    private byte[] mBufferData;
    private int mDataLength = 0;
    private Context mContext;
    private int mAudioBufferSize = 320;
    private boolean mIsRecording = false;
    private AudioProfile mAudioProfile;
    private BasicProfile mBasicProfile;
    private AudioRecord mAudioRecord = null;
    private RecordThread mRecordThread = null;
    private EncodeCallbackListener mEncodeCallbackListener;

    public AudioEncodeFun(Context context, AudioProfile audioProfile, BasicProfile basicProfile, EncodeCallbackListener listener) {
        mContext = context;
        mAudioProfile = audioProfile;
        mBasicProfile = basicProfile;
        mEncodeCallbackListener = listener;
    }

    public void setEncodeCallbackListener(EncodeCallbackListener listener) {
        mEncodeCallbackListener = listener;
    }

    public void startRecord() {
        startAsyncTask();
    }

    public void stopRecord() {
        if (mIsRecording) {
            Constant.isRecording = false;
            mEncodeCallbackListener.onAudioEncodeStatusCallback(false);
            JniProxy.m_CJniProxy.stopTransmit();
            try {
                if (mRecordThread != null)
                    mRecordThread.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    private void startAsyncTask() {
        AsyncTask<Integer, Integer, Integer> asyncTask = new AsyncTask<Integer, Integer, Integer>() {
            @Override
            protected Integer doInBackground(Integer... integers) {
                int flag = 0;
                if (KitUtil.checkNetworkConnection(mContext)) flag = 1;
                if (!JniProxy.m_CJniProxy.netConfig(mBasicProfile.serverAddress, mBasicProfile.cmdPort,
                        mBasicProfile.dataPort, mBasicProfile.transMode, mBasicProfile.routerMode, flag)) return -1;
                JniProxy.m_CJniProxy.startTransmit();
                startAudioRecord();
                return 0;
            }
        };
        asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
    }

    private void startAudioRecord() {
        if (mIsRecording) return;
        initAudioRecord();
    }

    private void initAudioRecord() {
        mCacheData = new byte[0];
        mBufferData = new byte[0];
        if (mAudioRecord == null) {
            int minBufferSize = AudioRecord.getMinBufferSize(mAudioProfile.rate, mAudioProfile.channel, mAudioProfile.bit);
            if (KitUtil.checkSDKVersion()) {
                mAudioRecord = new AudioRecord(MediaRecorder.AudioSource.VOICE_COMMUNICATION,
                        mAudioProfile.rate, mAudioProfile.channel, mAudioProfile.bit, minBufferSize * 2);
            } else {
                mAudioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC,
                        mAudioProfile.rate, mAudioProfile.channel, mAudioProfile.bit, minBufferSize * 2);
            }
        }
        mBuffer = new byte[mAudioBufferSize];
        mEncodeCallbackListener.onAudioEncodeStatusCallback(true);
        mIsRecording = true;
        if (mRecordThread == null) {
            mRecordThread = new RecordThread();
        }
        mRecordThread.start();
    }

    private void doRecord() {
        mAudioRecord.startRecording();
        while (mIsRecording) {
            int len = mAudioRecord.read(mBuffer,0, mAudioBufferSize);
            if (len == mAudioBufferSize) {
                sendAudioData(mBuffer, len);
            } else {
                Log.i("read audio", String.format("audio read too short %d/%d", len, mAudioBufferSize));
            }
        }
    }

    private void sendAudioData(byte[] buf, int len) {
        int dataLen = 320;
        int sendDataLen = 1024;
        //数据注入 缓存池扩容
        mDataLength += dataLen;
        mCacheData = Arrays.copyOf(mCacheData, mDataLength);
        System.arraycopy(buf, 0, mCacheData, mCacheData.length - dataLen, len);
        if (mCacheData.length > sendDataLen) {
            //取出数据
            byte[] result = new byte[sendDataLen];
            System.arraycopy(mCacheData, 0, result, 0, sendDataLen);
            JniProxy.m_CJniProxy.sendAudio(result, sendDataLen);
            //缓存池缩容后大小
            mBufferData = new byte[mCacheData.length - sendDataLen];
            //剩余数据提取到da中
            System.arraycopy(mCacheData, sendDataLen, mBufferData, 0, mCacheData.length - sendDataLen);
            //重置缓存
            mCacheData = mBufferData;
            //重置数据大小
            mDataLength = mBufferData.length;
        }
    }

    class RecordThread  extends Thread{

        @Override
        public void run() {
            doRecord();
        }
    }

}
